/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <bits/alltypes.h>
#include <locale>
#include <string>
#include <errno.h>
#include <string.h>
#include "pag_napi_pagFile.h"
#include "pag/file.h"
#include "pag/pag.h"
#include  "hilog/log.h"

namespace NativeXComponentSample {
const int32_t STR_DEFAULT_SIZE = 2048;
const int32_t INDEX_0 = 0;
const int32_t INDEX_1 = 1;
const int32_t INDEX_2 = 2;
const int32_t INDEX_3 = 3;
const int32_t PARAM_COUNT_1 = 1;
const int32_t PARAM_COUNT_2 = 2;
const int32_t PARAM_COUNT_3 = 3;
const int32_t PARAM_COUNT_4 = 4;


std::shared_ptr<pag::PAGFile> g_pagFile = nullptr;
napi_ref PAGFile::sJSFileConstructor_ = nullptr;
std::string PAGFile::_msg = "";
const unsigned int LOG_PRINT_DOMAIN = 0XFF00;


PAGFile::~PAGFile()
{
    if (mRef != nullptr) {
        napi_delete_reference(mEnv, mRef);
    }
};

PAGFile::PAGFile(napi_env pEnv)
{
    mEnv = pEnv;
}

PAGFile::PAGFile(napi_env pEnv, napi_ref pRef)
{
    mEnv = pEnv;
    mRef = pRef;
}
void pagI(napi_env env, void *a, void *b) {}

napi_value PAGFile::LoadFromPath(napi_env env, napi_callback_info info)
{
    size_t argc = PARAM_COUNT_1;
    napi_value args[INDEX_1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    char url[1024] = {0};
    size_t charLen = 0;
    napi_get_value_string_utf8(env, args[0], url, STR_DEFAULT_SIZE, &charLen);

    std::string urlPath = url;
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "INIT", "pag::File::Load(urlPath).get() %{public}s", url);
    g_pagFile = pag::PAGFile::Load(urlPath);
    return nullptr;
}

void PAGFile::Destructor(napi_env env, void *nativeObject, void *finalize)
{
    PAGFile *pagFile = reinterpret_cast<PAGFile *>(nativeObject);
    pagFile->PAGFile::~PAGFile();
}

napi_value PAGFile::JsFileConstructor(napi_env env, napi_callback_info info)
{
    napi_value undefineVar = nullptr;
    napi_value thisVar = nullptr;
    napi_get_undefined(env, &undefineVar);

    if (napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr) == napi_ok && thisVar != nullptr) {
        // 创建NapiTest 实例
        PAGFile *reference = new PAGFile(env);
        // 绑定实例类创建NapiTest到导出的对象result
        if (napi_wrap(env, thisVar, reinterpret_cast<void *>(reference), PAGFile::Destructor,
            nullptr, &(reference->mRef)) == napi_ok) {
            return thisVar;
        }
        return thisVar;
    }
    return undefineVar;
}

napi_value PAGFile::SetStartTime(napi_env env, napi_callback_info info)
{
    napi_value result = nullptr;
    int32_t startTime = 0;
    size_t argc = PARAM_COUNT_1;
    napi_value argv[INDEX_1] = {nullptr};
    napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);

    napi_get_value_int32(env, argv[0], &startTime);
    g_pagFile->setStartTime(startTime);
    return result;
}

napi_value PAGFile::SetDuration(napi_env env, napi_callback_info info)
{
    napi_value result = nullptr;
    int64_t duraTion = 0;
    size_t argc = PARAM_COUNT_1;
    napi_value argv[INDEX_1] = {nullptr};
    napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);

    napi_get_value_int64(env, argv[0], &duraTion);
    g_pagFile->setDuration(duraTion);
    return result;
}

napi_value PAGFile::Duration(napi_env env, napi_callback_info info)
{
    napi_value result;
    napi_create_int64(env, g_pagFile->duration(), &result);
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "INIT", "pag::File::Duration %{public}ld", g_pagFile->duration());
    return result;
}

napi_value PAGFile::NumImage(napi_env env, napi_callback_info info)
{
    napi_value result;
    napi_status status = napi_create_int32(env, g_pagFile->numImages(), &result);
    if (status != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get numImages fail!");
    }
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get numImages = %{public}d",
                 g_pagFile->numImages());
    return result;
}

napi_value PAGFile::NumTexts(napi_env env, napi_callback_info info)
{
    napi_value result;
    napi_status status = napi_create_int32(env, g_pagFile->numTexts(), &result);
    if (status != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get numtexts fail!");
    }
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get numtexts = %{public}d",
                 g_pagFile->numTexts());
    return result;
}

napi_value PAGFile::NumVideos(napi_env env, napi_callback_info info)
{
    napi_value result;
    napi_status status = napi_create_int32(env, g_pagFile->numVideos(), &result);
    if (status != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get numVideos fail!");
    }
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get numVideos = %{public}d",
                 g_pagFile->numVideos());
    return result;
}

napi_value PAGFile::Path(napi_env env, napi_callback_info info)
{
    napi_value result;
    napi_status status = napi_create_string_utf8(env, g_pagFile->path().c_str(), g_pagFile->path().size(), &result);
    if (status != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get path fail!");
    }
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get path = %{public}s",
                 g_pagFile->path().c_str());

    return result;
}

napi_value PAGFile::MaxSupportedTagLevel(napi_env env, napi_callback_info info)
{
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get MaxSupportedTagLevel!!!");
    napi_value result;
    napi_status status = napi_create_uint32(env, g_pagFile->MaxSupportedTagLevel(), &result);
    if (status != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get MaxSupportedTagLevel fail!");
    }
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get MaxSupportedTagLevel = %{public}d",
                 g_pagFile->MaxSupportedTagLevel());
    return result;
}

napi_value PAGFile::GetEditableIndices(napi_env env, napi_callback_info info)
{
    napi_value result;

    size_t argc = PARAM_COUNT_1;
    napi_value args[INDEX_1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    int32_t layerType;
    napi_status status = napi_get_value_int32(env, args[0], &layerType);
    if (status != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get MaxSupportedTagLevel fail!");
    }

    std::vector<int32_t> indices = g_pagFile->getEditableIndices(static_cast<pag::LayerType>(layerType));

    napi_create_array_with_length(env, indices.size(), &result);
    for (int32_t i = 0; i < indices.size(); ++i) {
        napi_value element;
        napi_create_int32(env, indices[i], &element);
        napi_set_element(env, result, i, element);
    }
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get GetEditableIndices ok!");
    return result;
}

napi_value PAGFile::TimeStretchMode(napi_env env, napi_callback_info info)
{
    napi_value result;
    napi_status status = napi_create_int32(env, g_pagFile->timeStretchMode(), &result);
    if (status != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get TimeStretchMode fail!");
    }
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get TimeStretchMode = %{public}d",
                 g_pagFile->timeStretchMode());

    return result;
}

napi_value PAGFile::TagLevel(napi_env env, napi_callback_info info)
{
    napi_value result;
    napi_status status = napi_create_int32(env, g_pagFile->tagLevel(), &result);
    if (status != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get tagLevel fail!");
    }
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PAGFile", "PAGFile get tagLevel = %{public}d",
                 g_pagFile->tagLevel());

    return result;
}

napi_value PAGFile::SetTimeStretchMode(napi_env env, napi_callback_info info)
{
    size_t argc = PARAM_COUNT_1;
    napi_value args[INDEX_1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    int32_t timeStretchMode;
    napi_get_value_int32(env, args[0], &timeStretchMode);

    g_pagFile->setTimeStretchMode(static_cast<pag::Enum>(timeStretchMode));
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "INIT", "PAGFile::SetTimeStretchMode %{public}d",
                 timeStretchMode);
    return nullptr;
}
} // namespace NativeXComponentSample